package com.lyn.solitude.pluginhost.database

import android.annotation.SuppressLint
import android.app.Application
import android.content.ContentValues
import android.provider.SyncStateContract.Helpers.update
import android.util.Log
import com.alibaba.fastjson.JSON
import com.lyn.solitude.entity.Plugin

/**
 *
 * @author longyn 2024/05/24
 * @version 1.0.0
 */
object SqliteManager {

    const val TAG = "SqliteManager"

    private lateinit var sqLiteOpenHelper: ISQLiteOpenHelper

    @JvmStatic
    fun initialize(application: Application) {
        if (this::sqLiteOpenHelper.isInitialized) {
            return
        }
        sqLiteOpenHelper = ISQLiteOpenHelper(application, "solitude_host")

    }

    @JvmStatic
    fun save(plugin: Plugin):Boolean{
        try {
            val findByIdFirst = findByIdFirst(plugin.id)
            findByIdFirst?.let {
                return update(plugin)
            }
            val contentValues = ContentValues()
            val clazz = Plugin::class.java
            val fields = clazz.declaredFields
            for (field in fields) {
                field.isAccessible = true
                val name = field.name
                if (name == "id"){
                    continue
                }
                val value = field.get(plugin)
                val type = field.type
                when (type) {
                    String::class.java -> {
                        contentValues.put(name, value?.toString() ?: "")
                    }

                    Long::class.java -> {
                        contentValues.put(name, value as Long)
                    }

                    Int::class.java -> {
                        contentValues.put(name, value as Int)
                    }

                    Boolean::class.java -> {
                        if (value as Boolean) {
                            contentValues.put(name, 1)
                        } else {
                            contentValues.put(name, 0)
                        }
                    }
                }
            }
            val insert =
                sqLiteOpenHelper.writableDatabase.insert("plugin",null, contentValues)
            return insert > 0
        } catch (e: Throwable) {
            e.printStackTrace()
        }
        return false
    }

    @JvmStatic
    @SuppressLint("Recycle", "Range")
    fun findAll(): MutableList<Plugin> {
        val list: MutableList<Plugin> = mutableListOf()
        val cursor = sqLiteOpenHelper.writableDatabase.query(
            "plugin",
            null,
            null,
            null,
            null,
            null,
            null
        )
        if (cursor != null && cursor.moveToFirst()) {
            do {
                val clazz = Plugin::class.java
                val fields = clazz.declaredFields
                val plugin = Plugin()
                for (field in fields) {
                    field.isAccessible = true
                    val name = field.name
                    val type = field.type
                    when (type) {
                        String::class.java -> {
                            val value = cursor.getString(cursor.getColumnIndex(name))
                            field.set(plugin, value)
                        }

                        Long::class.java -> {
                            val value = cursor.getLong(cursor.getColumnIndex(name))
                            field.set(plugin, value)
                        }

                        Int::class.java -> {
                            val value = cursor.getInt(cursor.getColumnIndex(name))
                            field.set(plugin, value)
                        }

                        Boolean::class.java -> {
                            val value = cursor.getInt(cursor.getColumnIndex(name))
                            field.set(plugin, (value == 1))
                        }
                    }
                }
                list.add(plugin)
            } while (cursor.moveToNext())
        }
        cursor.close()
        return list
    }

    @JvmStatic
    @SuppressLint("Recycle", "Range")
    fun findByIdFirst(id: Long): Plugin? {
        val cursor = sqLiteOpenHelper.writableDatabase.query(
            "plugin",
            null,
            "id=?",
            arrayOf(id.toString()),
            null,
            null,
            null
        )
        try {
            if (cursor != null && cursor.moveToFirst()) {
                val clazz = Plugin::class.java
                val fields = clazz.declaredFields
                val plugin = Plugin()
                for (field in fields) {
                    field.isAccessible = true
                    val name = field.name
                    val type = field.type
                    when (type) {
                        String::class.java -> {
                            val value = cursor.getString(cursor.getColumnIndex(name))
                            field.set(plugin, value)
                        }

                        Long::class.java -> {
                            val value = cursor.getLong(cursor.getColumnIndex(name))
                            field.set(plugin, value)
                        }

                        Int::class.java -> {
                            val value = cursor.getInt(cursor.getColumnIndex(name))
                            field.set(plugin, value)
                        }

                        Boolean::class.java -> {
                            val value = cursor.getInt(cursor.getColumnIndex(name))
                            field.set(plugin, (value == 1))
                        }
                    }
                }
                return plugin
            }
        } catch (e: Throwable) {
            e.printStackTrace()
        } finally {
            cursor?.close()
        }
        return null
    }

    @JvmStatic
    @SuppressLint("Recycle", "Range")
    fun findByUUidFirst(uuid: String): Plugin? {
        val cursor = sqLiteOpenHelper.writableDatabase.query(
            "plugin",
            null,
            "uuid=?",
            arrayOf(uuid),
            null,
            null,
            null
        )
        try {
            if (cursor != null && cursor.moveToFirst()) {
                val clazz = Plugin::class.java
                val fields = clazz.declaredFields
                val plugin = Plugin()
                for (field in fields) {
                    field.isAccessible = true
                    val name = field.name
                    val type = field.type
                    when (type) {
                        String::class.java -> {
                            val value = cursor.getString(cursor.getColumnIndex(name))
                            field.set(plugin, value)
                        }

                        Long::class.java -> {
                            val value = cursor.getLong(cursor.getColumnIndex(name))
                            field.set(plugin, value)
                        }

                        Int::class.java -> {
                            val value = cursor.getInt(cursor.getColumnIndex(name))
                            field.set(plugin, value)
                        }

                        Boolean::class.java -> {
                            val value = cursor.getInt(cursor.getColumnIndex(name))
                            field.set(plugin, (value == 1))
                        }
                    }
                }
                return plugin
            }
        } catch (e: Throwable) {
            e.printStackTrace()
        } finally {
            cursor?.close()
        }
        return null
    }

    @JvmStatic
    @SuppressLint("Recycle", "Range")
    fun findByFilePathFirst(filePath: String): Plugin? {
        val cursor = sqLiteOpenHelper.writableDatabase.query(
            "plugin",
            null,
            "filePath=?",
            arrayOf(filePath),
            null,
            null,
            null
        )
        try {
            if (cursor != null && cursor.moveToFirst()) {
                val clazz = Plugin::class.java
                val fields = clazz.declaredFields
                val plugin = Plugin()
                for (field in fields) {
                    field.isAccessible = true
                    val name = field.name
                    val type = field.type
                    when (type) {
                        String::class.java -> {
                            val value = cursor.getString(cursor.getColumnIndex(name))
                            field.set(plugin, value)
                        }

                        Long::class.java -> {
                            val value = cursor.getLong(cursor.getColumnIndex(name))
                            field.set(plugin, value)
                        }

                        Int::class.java -> {
                            val value = cursor.getInt(cursor.getColumnIndex(name))
                            field.set(plugin, value)
                        }

                        Boolean::class.java -> {
                            val value = cursor.getInt(cursor.getColumnIndex(name))
                            field.set(plugin, (value == 1))
                        }
                    }
                }
                return plugin
            }
        } catch (e: Throwable) {
            e.printStackTrace()
        } finally {
            cursor?.close()
        }
        return null
    }

    @JvmStatic
    fun update(plugin: Plugin): Boolean {
        try {
            val contentValues = ContentValues()
            val clazz = Plugin::class.java
            val fields = clazz.declaredFields
            for (field in fields) {
                field.isAccessible = true
                val name = field.name
                val value = field.get(plugin)
                val type = field.type
                if (name == "id"){
                    continue
                }
                when (type) {
                    String::class.java -> {
                        contentValues.put(name, value?.toString() ?: "")
                    }

                    Long::class.java -> {
                        contentValues.put(name, value as Long)
                    }

                    Int::class.java -> {
                        contentValues.put(name, value as Int)
                    }

                    Boolean::class.java -> {
                        if (value as Boolean) {
                            contentValues.put(name, 1)
                        } else {
                            contentValues.put(name, 0)
                        }
                    }
                }
            }
            val update =
                sqLiteOpenHelper.writableDatabase.update("plugin", contentValues, "id=?", arrayOf(plugin.id.toString()))
            Log.d(TAG, "update:$update")
            return update > 0
        } catch (e: Throwable) {
            e.printStackTrace()
        }
        return false
    }

    @JvmStatic
    fun delete(id: Long): Boolean {
        val delete =
            sqLiteOpenHelper.writableDatabase.delete("plugin", "id=?", arrayOf(id.toString()))
        return delete > 0
    }
}